import React, { useEffect, useState } from "react";
import moment from "moment";
import {
    Form,
    Rate,
    TimePicker,
    Checkbox,
    Cascader,
    Switch,
    Input,
    Select,
    Radio,
    InputNumber,
    DatePicker,
    Slider,
} from "antd";
import * as validateParams from "../config/validate";
import "./index.less";

let draging: any = null;

const Option = Select.Option;
const CheckboxGroup = Checkbox.Group;
const { RangePicker } = DatePicker;
let targetName = "drag-move"; //需要换位目标
let targetIndex = -1; //当前换位位置
let prevIndex = -1; //原坐标
const UiForm = (props) => {
    const {
        formList,
        newParams,
        setList,
        dragEnd,
        valid,
        setValid,
        setActive,
        active,
    } = props;

    // render 表单
    function renderForm(arr) {
        return arr.map((item, index) => {
            if (!item || !item.label) return;
            return (
                <div
                    key={index}
                    onClick={setActive.bind(this, index)}
                    onDragStart={dragStartFn.bind(this, index)}
                    onDragOver={dragOverFn.bind(this, index)}
                    onDragEnd={dragEndFn.bind(this)}
                    draggable
                    className={`drag-move drag-item drag-item-${
                        active == index ? "active" : ""
                    }`}
                >
                    <Form.Item
                        label={item.label}
                        name={index}
                        hasFeedback
                        rules={[
                            {
                                required: item.required,
                                message: item.tips,
                            },
                            {
                                validator: validateParams[item.rule],
                            },
                        ]}
                    >
                        {renderSwatch(item, index)}
                    </Form.Item>
                </div>
            );
        });
    }
    // render 表单类型判定
    function renderSwatch(item, index) {
        switch (item.type) {
            case "Input":
                return (
                    <Input
                        allowClear={
                            item.allowClear === undefined
                                ? true
                                : item.allowClear
                        }
                        onChange={checkNoSpace.bind(this, index)}
                        placeholder={item.tips}
                        key={index}
                        value={item.value}
                        disabled={item.disabled}
                    />
                );
            case "InputNumber":
                return (
                    <InputNumber
                        min={item.min}
                        onChange={checkNoSpace.bind(this, index)}
                        placeholder={item.tips}
                        key={index}
                        value={item.value}
                        disabled={item.disabled}
                    />
                );
            case "Select":
                return (
                    <Select
                        disabled={item.disabled}
                        showSearch
                        mode={item.mode}
                        onChange={checkNoSpace.bind(this, index)}
                        placeholder={item.tips}
                        allowClear={
                            item.allowClear === undefined
                                ? true
                                : item.allowClear
                        }
                        value={item.value}
                        key={index}
                        filterOption={(input, option) =>
                            (option!.children as unknown as string).includes(
                                input
                            )
                        }
                    >
                        {item.options.map((its) => {
                            return (
                                <Option key={its.value} value={its.value}>
                                    {" "}
                                    {its.label}{" "}
                                </Option>
                            );
                        })}{" "}
                    </Select>
                );
            case "Radio":
                return (
                    <Radio.Group
                        disabled={item.disabled}
                        onChange={checkNoSpace.bind(this, index)}
                        key={index}
                        value={item.value}
                    >
                        {item.options.map((its) => {
                            return (
                                <Radio key={its.value} value={its.value}>
                                    {" "}
                                    {its.label}{" "}
                                </Radio>
                            );
                        })}
                    </Radio.Group>
                );
            case "Checkbox":
                return (
                    <CheckboxGroup
                        disabled={item.disabled}
                        onChange={checkNoSpace.bind(this, index)}
                        key={index}
                        options={item.options}
                        value={item.value}
                    />
                );
            case "Rate":
                return (
                    <Rate
                        disabled={item.disabled}
                        allowClear={
                            item.allowClear === undefined
                                ? true
                                : item.allowClear
                        }
                        onChange={checkNoSpace.bind(this, index)}
                        key={index}
                        allowHalf
                        value={item.value}
                    />
                );
            case "Switch":
                return (
                    <Switch
                        disabled={item.disabled}
                        onChange={checkNoSpace.bind(this, index)}
                        checked={item.value}
                        key={index}
                    />
                );
            case "Slider":
                return (
                    <Slider
                        disabled={item.disabled}
                        onChange={checkNoSpace.bind(this, index)}
                        value={item.value}
                    />
                );
            case "Cascader":
                return (
                    <Cascader
                        disabled={item.disabled}
                        onChange={checkNoSpace.bind(this, index)}
                        key={index}
                        allowClear={
                            item.allowClear === undefined
                                ? true
                                : item.allowClear
                        }
                        value={item.value}
                        options={item.options}
                        placeholder={item.tips}
                    />
                );
            case "TimePicker":
                return (
                    <TimePicker
                        disabled={item.disabled}
                        showNow={item.showToday}
                        inputReadOnly={item.inputReadOnly}
                        onChange={checkNoSpace.bind(this, index)}
                        key={index}
                        value={item.value}
                    />
                );
            case "DatePicker":
                return (
                    <DatePicker
                        disabled={item.disabled}
                        showToday={item.showToday}
                        inputReadOnly={item.inputReadOnly}
                        onChange={checkSetTime.bind(this, index)}
                        placeholder={item.tips}
                        key={index}
                        value={item.value}
                    />
                );
            case "RangePicker":
                return (
                    <RangePicker
                        disabled={item.disabled}
                        inputReadOnly={item.inputReadOnly}
                        format={item.format ? item.format : "YY-MM-DD HH:mm:ss"}
                        showTime
                        allowClear={
                            item.allowClear === undefined
                                ? true
                                : item.allowClear
                        }
                        value={item.value}
                        showNow={false}
                        key={index}
                        placeholder={item.tips}
                        onChange={checkSetArrTime.bind(this, index)}
                        onOk={checkSetArrTime.bind(this, index)}
                    />
                );
            default:
                return "";
        }
    }
    // fn 拖动开始
    function dragStartFn(index, e) {
        e.dataTransfer.setData("te", e.target.innerText); //不能使用text，firefox会打开新tab
        draging = e.target;
        prevIndex = index;
    }
    // fn 拖动中
    function dragOverFn(index, e) {
        e.preventDefault();
        let target = getParentNode(e.target);
        if (!target || target.className.includes(targetName)) return;
        if (target !== draging) {
            targetIndex = index;
        }
    }
    // fn 拖动结束
    function dragEndFn() {
        if (prevIndex === -1 || targetIndex === -1) return;
        let newList = [...formList];
        let prev = newList[prevIndex];
        let target = newList[targetIndex];
        newList.splice(prevIndex, 1, target);
        newList.splice(targetIndex, 1, prev);
        setList(newList);
    }
    // fn 新生成元素
    function dargAddFn() {
        // 直接新增
        if (!dragEnd || !newParams.label) return;
        if (targetIndex === -1) {
            setList([...formList, newParams]);
        } else {
            let newlist = [...formList];
            newlist.splice(targetIndex, 0, newParams);
            setList(newlist);
        }
    }
    // 阶梯查询父级元素
    function getParentNode(el) {
        try {
            if (el.className === "") return getParentNode(el.parentNode);
            if (el.className.includes(targetName)) return el;
            let parentName = el.parentNode.className;
            if (parentName.includes(targetName))
                return getParentNode(el.parentNode);
            if (!parentName.includes(targetName)) return el.parentNode;
        } catch (error) {
            console.log(error);
            console.log(el.className);
            return undefined;
        }
    }
    // 时间选择传值
    function checkSetTime(index, val) {
        let newList = [...formList];
        newList[index].value = moment(val._d).format("YYYY-MM-DD");
        setList(newList);
    }
    // 时间区间选择传值
    function checkSetArrTime(index, val) {
        let param;
        if (val === null) param = val;
        else if (val[1] != null) param = moment(val[1]._d).format("YYYY-MM-DD");
        else param = moment(val[0]._d).format("YYYY-MM-DD");

        let newList = [...formList];
        newList[index].value = param;
        setList(newList);
    }
    // 表单传值
    function checkNoSpace(index, e) {
        let param = e && e.target ? e.target.value : e;
        let newList = [...formList];
        newList[index].value = param;
        setList(newList);
    }

    useEffect(() => {
        if (valid) dargAddFn();
        if (dragEnd) {
            draging = null;
            targetIndex = -1;
        }
    }, [dragEnd]);

    return (
        <div
            onDragEnter={(e) => {
                if (valid) return;
                e.preventDefault();
                setValid(true);
            }}
            id="uiform"
            className="uiform"
        >
            <Form>{renderForm(formList)}</Form>
        </div>
    );
};
export default UiForm;
